package main

import (
	"context"
	"os"
	"os/signal"
	"strings"
	"sync"
	"sync/atomic"
	"syscall"
	"time"
	"ug-uploads/config"
	"ug-uploads/db"
	"ug-uploads/fetcher"
	"ug-uploads/initialize"
	"ug-uploads/logx"

	"github.com/panjf2000/ants/v2"
	"go.uber.org/zap"
)

func main() {
	initialize.Init()
	defer logx.Logger.Sync()
	defer db.CloseSqlite()
	//广告主id个数
	initialize.StatsInfo.AdvertiserCount = int64(len(config.Cfg.AdvertiserIDs))
	//协程池设定为广告主个数
	poolSize := int(initialize.StatsInfo.AdvertiserCount)

	// pool, _ := ants.NewPool(size,
	// 	ants.WithPreAlloc(true),        // 提前分配内存，提高性能
	// 	ants.WithNonblocking(true),     // 提交超出池容量的任务会立即返回错误
	// 	ants.WithMaxBlockingTasks(100), // 最大等待任务数
	// )

	pool, _ := ants.NewPool(poolSize, ants.WithPreAlloc(true))
	defer pool.Release()
	logx.Logger.Info("创建协程池", zap.Int("size", poolSize))
	//退出信号监听
	stop := make(chan os.Signal, 1)
	signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
	ticker := time.NewTicker(60 * time.Minute)
	defer ticker.Stop()

	for {
		wg := sync.WaitGroup{}
		startTime := time.Now()

		for _, id := range config.Cfg.AdvertiserIDs {
			id = strings.TrimSpace(id)

			if id == "" {
				continue
			}

			wg.Add(1)

			task := func(advertiserID string) func() {
				return func() {
					defer wg.Done()
					taskCtx, cancel := context.WithTimeout(context.Background(), 50*time.Minute)
					defer cancel()
					start := time.Now()
					err := fetcher.FetchAndUpload(taskCtx, advertiserID)
					if err != nil {
						logx.Logger.Error("任务执行失败", zap.String("advertiser_id", advertiserID), zap.Error(err))
					} else {
						logx.Logger.Info("任务完成", zap.String("advertiser_id", advertiserID), zap.Duration("耗时", time.Since(start)))
					}
				}
			}(id)

			if err := pool.Submit(task); err != nil {
				logx.Logger.Error("提交协程任务失败", zap.Error(err))
				wg.Done()
			}
		}

		wg.Wait()
		duration := time.Since(startTime)

		logx.Logger.Info("本轮任务完成",
			zap.Int64("成功", atomic.LoadInt64(&initialize.StatsInfo.Success)),
			zap.Int64("跳过", atomic.LoadInt64(&initialize.StatsInfo.JumpCount)),
			zap.String("耗时", duration.String()),
		)

		//重置计数
		initialize.ResetCounter()
		logx.Logger.Info("等待下一轮")

		select {
		case <-ticker.C:
			continue
		case <-stop:
			logx.Logger.Info("接收到退出信号, 程序结束")
			return
		}
	}
}
